#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>

// 等待一子个进程
// int main()
// {
//     pid_t id = fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         return 1;
//     }
//     else if(id == 0)
//     {
//         // child
//         int cnt = 5;
//         while(cnt)
//         {
//             printf("I am a child, pid: %d, ppid: %d, cnt: %d\n",getpid(),getppid(), cnt);
//             sleep(1);
//             cnt--;
//         }
//         exit(0);
//     }
//     else
//     {
//         // parent
//         int cnt = 10;
//         while(cnt)
//         {
//             printf("I am a parent, pid: %d, ppid: %d, cnt: %d\n",getpid(),getppid(), cnt);
//             sleep(1);
//             cnt--;
//         }
//         pid_t wid = wait(NULL);
//         if(wid == id)
//         {
//             printf("wait success, wid: %d\n",wid);
//         }
//         sleep(5);
//     }
//     return 0;
// }

// 等待多个子进程
// #define N 5

// void runChild()
// {
//     // child
//     int cnt = 5;
//     while (cnt)
//     {
//         printf("I am a child, pid: %d, ppid: %d, cnt: %d\n", getpid(), getppid(), cnt);
//         sleep(1);
//         cnt--;
//     }
//     exit(0);
// }
// int main()
// {
//     for (size_t i = 0; i < N; i++) // 一次性创建一批进程
//     {
//         pid_t id = fork();
//         if (id == 0)
//         {
//             // child
//             runChild();
//             exit(0);
//         }
//     }
//     sleep(10);
//     // 等待
//     for (size_t i = 0; i < N; i++) // 循环等待
//     {
//         pid_t wid = wait(NULL);
//         if (wid > 0)
//         {
//             printf("wait %d success\n", wid);
//         }
//     }

//     return 0;
// }

// 获取子进程退出信息——waitpid
// int main()
// {
//     pid_t id = fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         return 1;
//     }
//     else if(id == 0)
//     {
//         // child
//         int* p = NULL;
//         int cnt = 5;
//         while(cnt)
//         {
//             printf("I am child, pid: %d, ppid: %d, cnt: %d\n",getpid(),getppid(), cnt);
//             cnt--,sleep(1);
//             *p = 100;       // 故意制作一个空指针错误
//         }
//         exit(66);       // 将子进程退出码设为66；
//     }
//     else
//     {
//         // parent
//         int cnt = 7;
//         while (cnt)
//         {
//             printf("I am parent, pid: %d, ppid: %d, cnt: %d\n",getpid(),getppid(), cnt);
//             cnt--,sleep(1);
//         }
//         // 开始进行进程等待

//         // int status = 0;
//         // pid_t ret = waitpid(id, &status, 0);    // option参数设为0
//         // if(ret == id)
//         // {
//         //     // 等待成功
//         //     // 7F: 0111 1111
//         //     printf("wait success, ret: %d, exit sig: %d, exit code: %d\n", ret, status&0x7F, (status>>8)&0xFF);
//         // }

//         //
//         int status = 0;
//         pid_t ret = waitpid(id, &status, 0);
//         if(ret == id)
//         {
//             if(WIFEXITED(status))
//             {
//                 printf("进程时正常跑完的，退出码：%d\n",WEXITSTATUS(status));
//             }
//             else
//             {
//                 printf("进程出现异常了\n");
//             }
//         }

//         sleep(3);
//     }
//     return 0;
// }

// 非阻塞轮询等待

#define Task_Num 10
typedef void(*task_t)();
task_t tasks[Task_Num];

void task1()
{
    printf("这是一个打印日志的任务， pid: %d\n",getpid());
}

void task2()
{
    printf("这是一个检测网络连接的任务， pid: %d\n",getpid());
}

void task3()
{
    printf("这是一个绘制图形化界面的任务， pid: %d\n",getpid());
}

void task4()
{
    printf("这是一个记录时间的任务， pid: %d\n",getpid());
}

//将任务添加到tasks中
int AddTask(task_t t)
{
    int pos = 0;
    for(; pos < Task_Num; pos++)
    {
        if(!tasks[pos]) break;
    }
    if(pos == Task_Num) 
    {
        printf("数组空间不足\n");
        return -1;
    }
    tasks[pos] = t;
    return 0;
}

void InitTask()
{
    for (int i = 0; i < Task_Num; i++)
    {
        tasks[i] = NULL;
    }
    AddTask(task1);
    AddTask(task2);
    AddTask(task3);
    AddTask(task4);
}

void DelTask(task_t t)
{
    int size = 0;
    for (size_t i = 0; i < Task_Num; i++)
    {
        if(tasks[i]) size++;
    }
    
    for (int i = 0; i < Task_Num; i++)
    {
        if(tasks[i] == t)
        {
            // 开始删除
            int j = i;
            for (; j < Task_Num-1; j++)
            {
                tasks[j] = tasks[j+1];
            }
            tasks[size-1] = NULL;
            break;
        }
    }
    printf("没有该任务\n");
}

void CheckTask()
{}

void UpdateTask()
{}

void ExecuteTask()
{
    for(int i = 0; i < Task_Num; i++)
    {
        if(!tasks[i]) continue;
        tasks[i]();
    }
}

int main()
{
    pid_t id = fork();
    if (id < 0)
    {
        perror("fork()");
        return 1;
    }
    else if (id == 0)
    {
        // child
        int cnt = 5;
        while (cnt)
        {
            printf("I am child, pid: %d, ppid: %d, cnt: %d\n", getpid(), getppid(), cnt);
            cnt--;
            sleep(1);
        }
        exit(66);
    }
    else
    {
        int status = 0;
        InitTask();
        while (1)
        {
            pid_t ret = waitpid(id, &status, WNOHANG);
            if (ret > 0)
            {
                if (WIFEXITED(status))
                {
                    printf("进程是正常跑完的, 退出码:%d\n", WEXITSTATUS(status));
                }
                else
                {
                    printf("进程出异常了\n");
                }
                break;
            }
            else if (ret < 0)
            {
                printf("wait failed!\n");
                break;
            }
            else
            {
                printf("好了没有？子进程你还没有退出，我再等等...\n");
                ExecuteTask();
                sleep(1);
            }
        }
        int a = 0
        a /= 10;
    }
    return 0;
}